/*
 * CavityData.h
 *
 *  Created on: May 31, 2012
 *      Author: marchi
 */

#ifndef CAVITYDATA_H_
#define CAVITYDATA_H_
#include <iomanip>
#include <ostream>
#include <iostream>
#include <sstream>
#include <set>
#include <algorithm>
#include "Vertex.h"
#include <cmath>
#include <string>
#include "MyUtilClass.h"

using std::set;
using std::ostream;
using std::string;
using namespace MATRIX;
using namespace DVECT;
namespace Cavities{


class CavityData{
protected:
	Dvect p;
	set<double> rds;
	Vertex vtx;
	double Rmin;
public:
	CavityData(){};
	virtual ~CavityData(){};
	CavityData & operator()(const Vertex & x){
		vtx(x);
		return *this;
	}
	CavityData & operator()(const Dvect & x){
		p(x);
		return *this;
	}
	CavityData & operator()(const double & x){
		rds.insert(x);
		return *this;
	}
	CavityData & operator()(const double & x,const Dvect & y){
		rds.insert(x);
		p(y);
		return *this;
	}
	CavityData & operator()(const double & x,const Dvect & y, const Vertex & z){
		rds.insert(x);
		p(y);
		vtx(z);
		return *this;
	}
	const Dvect & gPoint() const {return p;}
	const Vertex & gVtx() const {return vtx;};
	const set<double> & gRadii() const {return rds;}
	double gMinRadius() const {return *(rds.begin());}
};
class SetCavityData {
protected:
	string str;
	Dvect p;
	set<double> rds;
	vector<int> atId;
	vector<int> tyId;
	static double eps;
	void loccopy(const std::pair<const Vertex,CavityData> & y){
		p=y.second.gPoint();
		rds=y.second.gRadii();
		atId=y.first.gnoVertex();
		tyId=y.second.gVtx().gnoVertex();
		std::stringstream ss;
		ss<< std::fixed << std::setprecision(0) << std::setw(7) << p[XX]/eps << " "<<p[YY]/eps<< " " <<p[ZZ]/eps;
		str=ss.str();
	}
	void ccopy(const SetCavityData & y){
		str=y.str;
		p=y.p;
		rds=y.rds;
		atId=y.atId;
		tyId=y.tyId;
	}
public:
	SetCavityData(){rds.clear();atId.clear();tyId.clear();};
	SetCavityData(double y){eps=y;};
	SetCavityData(const std::pair<const Vertex,CavityData> & y){loccopy(y);};
	virtual ~SetCavityData(){};
	SetCavityData & operator()(const std::pair<const Vertex,CavityData> & y){
		loccopy(y);
		return *this;
	}
	SetCavityData & operator=(const SetCavityData & y){
		ccopy(y);
		return *this;
	};

	SetCavityData & operator()(const SetCavityData & y){
		ccopy(y);
		return *this;
	};

	bool operator==(const SetCavityData & y) const {
		return str == y.str;
	}

	bool operator<(const SetCavityData & u) const {
		return str < u.str;
	}
	bool operator>(const SetCavityData & u) const {
		return str> u.str;
	}

	void Merge(const std::pair<const Vertex,CavityData> & y,const vector<int> & tnme){
		vector<int> mtmp=y.first.gnoVertex();
		copy(mtmp.begin(),mtmp.end(),back_inserter(atId));
		sort(atId.begin(),atId.end());
		atId.resize(unique(atId.begin(),atId.end())-atId.begin());

		tyId.clear();
		for(unsigned int n=0;n<atId.size();n++)
			tyId.push_back(tnme[atId[n]]);
		set<double>::iterator it=y.second.gRadii().begin();
		for(;it != y.second.gRadii().end();++it)
			rds.insert(*it);
	}
	const Dvect & gPoint() const {return p;}
	const set<double> & gRadii() const {return rds;}
	const vector<int> & gatId() const {return atId;};
	const vector<int> & gtyId() const {return tyId;};
	double gMinRadius() const {return *(rds.begin());}
};
}
#endif /* CAVITYDATA_H_ */
